import { fetchConfig, fetchConfigMethod } from './interface';
let config: fetchConfig = {
  url: '',
  data: {},
  statusCode: 200,
  header: {
    // "content-type":"application/json"
  },
  method: 'POST',
  timeout: 60000,
  dataType: 'json',
  responseType: 'text',
  sslVerify: true,
  withCredentials: false,
  firstIpv4: false,
};

function request(
  cog: fetchConfig = config,
  complete?: Function,
  beforeRequest?: Function,
  afterRequest?: Function
): Promise<UniApp.GeneralCallbackResult | UniApp.RequestSuccessCallbackResult> {
  let newConfig = { ...config, ...cog };
  return new Promise(async (resolve, reject) => {
    if (typeof beforeRequest === 'function') {
      let opts = await beforeRequest(newConfig);
      if (typeof opts !== 'object') {
        opts = {};
      }
      newConfig = { ...newConfig, ...opts };
    }
    uni.request({
      url: newConfig.url || '',
      data: newConfig.data,
      header: newConfig.header,
      method: newConfig.method,
      timeout: newConfig.timeout,
      dataType: newConfig.dataType,
      responseType: newConfig.responseType,
      sslVerify: newConfig.sslVerify,
      withCredentials: newConfig.withCredentials,
      firstIpv4: newConfig.firstIpv4,
      async success(result) {
        if (result.statusCode !== newConfig?.statusCode) {
          reject(result);
          return;
        }
        if (typeof afterRequest === 'function') {
          let opts = await afterRequest(result);

          try {
            if (typeof opts !== 'object') {
              opts = result;
            }
            if (typeof opts === 'object' && Object.keys(opts)?.length == 0) {
              opts = result;
            }
          } catch (e) {
            console.error('tmui:', e);
          }
          result = { ...opts };
        }
        resolve(result);
      },
      fail(result) {
        reject(result);
      },
      complete(result) {
        if (typeof complete === 'function') {
          complete(result);
        }
      },
    });
  });
}
var beforeRequest: Function = (val: fetchConfig) => val;
var afterRequest: Function = (val: fetchConfig) => val;
export class fetchNet {
  /**
   * 构建新的请求
   * @param cog 请示配置见：fetchConfig
   * @param beforeRequest 访问前执行的函数，可以是Promise,你可以对执行前的参数进行修改之类的，将以你最新的修改参数为准进行请求。
   * @param afterRequest 访问后执行的函数，可以是Promise,提供请示后的数据，你可以在这里修改，返回，这样所有请求的数据返回后都为返回你修改后的数据。
   */
  constructor(cog: fetchConfig, beforeRequestFun?: Function, afterRequesFunt?: Function) {
    config = { ...config, ...(cog || {}) };
    if (typeof beforeRequestFun == 'function') {
      beforeRequest = beforeRequestFun;
    }
    if (typeof afterRequesFunt == 'function') {
      afterRequest = afterRequesFunt;
    }
  }
  static get(url: string, data: object = {}, opts: fetchConfig = {}) {
    let cfg: fetchConfig = { ...config, ...(opts || {}), url: url, method: 'GET', data: data };
    return request(cfg);
  }
  static post(url: string, data: object = {}, opts: fetchConfig = {}) {
    let cfg: fetchConfig = { ...config, ...(opts || {}), url: url, method: 'POST', data: data };
    return request(cfg);
  }
  /**
   * 请求
   * @param cog 配置
   * @param complete 访问结束后执行的函数
   */
  static async request(cog: fetchConfig = config, beforeFun?: Function, afterFun?: Function, complete?: Function) {
    let newConfig = { ...config, ...cog };
    if (typeof beforeFun == 'function') {
      let testFun = await beforeFun();
      let cb: UniApp.GeneralCallbackResult = { errMsg: '中止请求' };
      if (!testFun) return cb;
    }
    return request(newConfig, complete, beforeFun || beforeRequest, afterFun || afterRequest);
  }
}
